package com.ydzt.fanka.server.indb;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.dom4j.Element;

import com.ydzt.fanka.server.domain.Node;
import com.ydzt.fanka.server.domain.ParamDefine;
import com.ydzt.fanka.server.domain.ReturnInfo;
import com.ydzt.fanka.server.init.InitData;
import com.ydzt.fanka.server.log.LoggerFanka;
import com.ydzt.fanka.server.utils.ByteConvert;
import com.ydzt.fanka.server.utils.DBHelper;
import com.ydzt.fanka.server.utils.JdbcUtils;
import com.ydzt.fanka.server.utils.SqlUtil;

public class Indb {
	static Logger logger = Logger.getLogger(Indb.class.getName());
	private static Statement stmt;
	private static ResultSet rs;
	
	private static String tablename;
	private static List<Element> structure;
	private static int oneRecordLength;
	private static int headLength = 23;
	
	private static String fmt = "yyyyMMdd";
	@SuppressWarnings("unused")
	private static SimpleDateFormat sdf = new SimpleDateFormat(fmt);
	
	private Indb(){
	}
	
	private static final Indb indb = new Indb();
	
	public static Indb getInstance(){
		return indb;
	}
	
	
	
	/*
	 * 解包入库方法 根据传入的报文pkg 以及报文结构定义map 对报文进行解析 并存入数据库
	 * */
	public synchronized static ReturnInfo decodeInsertDB(byte[] pkg,HashMap<String , ParamDefine> map,Connection conn_old){
		String tablename_tmp = "";
		ReturnInfo returnInfo = new ReturnInfo();
		Connection conn = JdbcUtils.getConnectionForOracle();
		if(conn == null){
			returnInfo.setErrorType(InitData.jdbc_connect_error);
			returnInfo.setSuccess(false);
			return returnInfo;
		}
		@SuppressWarnings("unused")
		String errorType = "";
		List<Node> records = null;
		@SuppressWarnings("unused")
		boolean isCommit = false;
		String sqlText = null;
		List<String> sqlTextColl = new ArrayList<String>();
		String paramType = null;
		//int iParamType = 0;
		try {
			@SuppressWarnings("unused")
			Date dt = new Date();
			byte[] paramTypeBytes = new byte[2];
			System.arraycopy(pkg, 0, paramTypeBytes, 0, 2);
			paramType = ByteConvert.bcd2Str(paramTypeBytes);
			ParamDefine paramDefine = map.get(paramType);
			if(paramDefine != null){
				tablename  = paramDefine.getTablename();
				oneRecordLength = paramDefine.getOneRecordLength();
				structure = paramDefine.getStructure();
				records = new ArrayList<Node>();
				int recordCount = (pkg.length - headLength) / oneRecordLength;
				conn.setAutoCommit(false);
				stmt = conn.createStatement();
				int offset = 0;
				for(int i = 0;i < recordCount; i ++){
					String arr[] = tablename.split("_");
					//取arr最后一个元素
					//String dateStr = sdf.format(dt);
					String dateStr = DBHelper.getStmtDay();
					//交易明细表为月表，SPLIT为月份占位符 根据结算日期确定SPLIT的位置的具体的值
					if(arr[arr.length - 1].equals("SPLIT")){
						arr[arr.length - 1] = dateStr.substring(4, 6);
					}
					for(int k = 0;k < arr.length; k ++){
						if(k != arr.length - 1){
							tablename_tmp += arr[k];
							tablename_tmp += "_";
						}
						else
						{
							tablename_tmp += arr[k];
						}
					}
					for(Iterator<Element> it = structure.iterator(); it.hasNext();){
						Node recordInDB = new Node();
						Element elm = (Element)it.next();
						if(elm.attributeValue("Flag").trim().equals("0")){//需要进行入库
							String name = elm.attributeValue("Name");
							if(name == null){
								System.out.println("name不存在");
							}
							recordInDB.setName(name);
							String strValueLength = elm.attributeValue("Length");
							int valueLength = Integer.parseInt(strValueLength);
							recordInDB.setTypeLength(strValueLength);
							recordInDB.setValueType(elm.attributeValue("Type"));
							recordInDB.setValueType(elm.attributeValue("DbType"));
							byte[] value = new byte[valueLength];
							System.arraycopy(pkg, headLength + offset, value, 0, valueLength);
							offset += valueLength;
							recordInDB.setValue(value);
							records.add(recordInDB);
						}
						else{
							//虽然不入库 但是当前包长的指针要变  
							String strValueLength = elm.attributeValue("Length");
							int valueLength = Integer.parseInt(strValueLength);
							offset += valueLength;
						}
						
					}
					//根据单条记录拼接SQL语句
					sqlText = SqlUtil.createInsertSql(tablename_tmp, records);
					logger.info("执行:" + sqlText);
				    sqlTextColl.add(sqlText);
					records.clear();
					sqlText = null;
					tablename_tmp = "";
				}
				
				for(int i = 0;i < sqlTextColl.size(); i ++){
					stmt.addBatch(sqlTextColl.get(i));
					//logger.info(sqlTextColl.get(i));
				}
				//对拼接出来的sql语句进行批量提交
				int[] result = stmt.executeBatch(); 
				conn.commit();
				logger.info("本次入库      " + result.length + "   条记录");
				isCommit = true;
				conn.setAutoCommit(true);
				returnInfo.setErrorType("");
				returnInfo.setSuccess(true);
			}
			else{
				logger.error("解包入库时 未能取到 " + paramType + "参数的定义");
			}
		} catch (Exception e1) {
			try{
				if(conn != null){
					conn.rollback();
					conn.setAutoCommit(true);
					isCommit = false;
					logger.error("入库失败");
					logger.error("入库失败的报文为:");
					logger.error(LoggerFanka.dumpBin(pkg));
					logger.error(e1.getMessage());
				}
			}
			catch(SQLException e2){
				//e2.printStackTrace();
				returnInfo.setErrorType(InitData.jdbc_connect_error);
				returnInfo.setSuccess(false);
				logger.error(e2.getMessage());
				isCommit = false;
			}
		}
		finally{
			structure = null;
			sqlText = null;
			records.clear();
			//JdbcUtils.free(rs, stmt, conn);
			JdbcUtils.freeAll(rs, stmt, conn);
		}
		return returnInfo;
	}
}
